package com.fingard.dsp.bank.directbank.abc23.util;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;

public class RSAHelper {
	private static final String EncodingKey = "GBK";
	/**
	 * 私钥
	 */
	private PrivateKey _PriKey;
	/**
	 * 公钥
	 */
	private PublicKey _PubKey;
	/**
	 * 算法名称
	 */
	private String _SigAlgName;
	public RSAHelper()
	{
		
	}
	/**
	 * 使用 pfx 证书设置私钥
	 * @param keyStorePath
	 * @param alias
	 * @param password
	 * @throws KeyStoreException
	 * @throws NoSuchAlgorithmException
	 * @throws CertificateException
	 * @throws IOException
	 * @throws UnrecoverableKeyException
	 */
	public void setPrivateKeyByCert(String keyStorePath, String alias, String password) 
			throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException
	{
        // 获得证书
        X509Certificate x509Certificate = (X509Certificate) CertAndKeyHelper.getCertificate(keyStorePath, alias, password);
        // 获取私钥
        KeyStore keyStore = CertAndKeyHelper.getKeyStore(keyStorePath, password);
        // 取得私钥
        this._PriKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
        // 构建签名
        this._SigAlgName = x509Certificate.getSigAlgName();//"SHA1withRSA";
	}
	/**
	 * 使用 xml 文件设置私钥
	 * @param xmlFilePath
	 * @throws IOException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 */
	public void setPrivateKeyByXml(String xmlFilePath) 
			throws IOException, NoSuchAlgorithmException, InvalidKeySpecException
	{
        byte[] privateKeyBytes = IOHelper.fileToBytes(xmlFilePath);
        String privateKeyXmlString = new String(privateKeyBytes, EncodingKey);
        this._PriKey = CertAndKeyHelper.decodePrivateKeyFromXml(privateKeyXmlString);
        // 构建签名
        this._SigAlgName = "SHA1withRSA";
	}
	/**
	 * 使用 .cer 的证书设置公钥
	 * @param certificatePath
	 * @throws CertificateException
	 * @throws IOException
	 */
	public void setPublicKeyByCert(String certificatePath) 
			throws CertificateException, IOException
	{
        // 获得证书
        X509Certificate x509Certificate = (X509Certificate) CertAndKeyHelper.getCertificate(certificatePath);
        // 获得公钥
        this._PubKey = x509Certificate.getPublicKey();
        // 构建签名
        this._SigAlgName = x509Certificate.getSigAlgName();//"SHA1withRSA";
	}
	/**
	 * 使用 xml 文件设置公钥
	 * @param xmlFilePath
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 * @throws IOException
	 */
	public void setPublicKeyByXml(String xmlFilePath) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException 
	{
        byte[] publicKeyBytes = IOHelper.fileToBytes(xmlFilePath);
        String publicKeyXmlString = new String(publicKeyBytes, this.EncodingKey);
        this._PubKey = CertAndKeyHelper.decodePublicKeyFromXml(publicKeyXmlString);
        this._SigAlgName = "SHA1withRSA";
	}
	/**
	 * 对 Base64 编码的源数据进行签名，返回签名后的值的 Base64 值
	 * @param dataBase64
	 * @return
	 * @throws NoSuchAlgorithmException 
	 * @throws SignatureException 
	 * @throws InvalidKeyException 
	 */
	public String sign(String dataBase64) throws InvalidKeyException, SignatureException, NoSuchAlgorithmException
	{
		byte[] signatureData = sign(Base64Helper.decode(dataBase64));
		return Base64Helper.encode(signatureData);
	}
	/**
	 * 对 源数据进行签名，返回签名后的值
	 * @param data
	 * @return
	 * @throws SignatureException 
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeyException 
	 */
	public byte[] sign(byte[] data) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException
	{
        // 构建签名
        String sigAlgName = this._SigAlgName;
        Signature signature = Signature.getInstance(sigAlgName);
        signature.initSign(this._PriKey);
        signature.update(data);
        return signature.sign();
	}
	/**
	 * 对 Base64 编码的源数据,和签名后的值的 Base64 值进行验签
	 * @param dataBase64
	 * @param signatureDataBase64
	 * @return
	 * @throws NoSuchAlgorithmException 
	 * @throws SignatureException 
	 * @throws InvalidKeyException 
	 */
	public boolean verifySign(String dataBase64, String signatureDataBase64) throws InvalidKeyException, SignatureException, NoSuchAlgorithmException
	{
		byte[] data = Base64Helper.decode(dataBase64);
		byte[] signatureData = Base64Helper.decode(signatureDataBase64);
		return verifySign(data, signatureData);
	}
	/**
	 * 对 源数据和签名后的值进行验签
	 * @param data
	 * @param signatureData
	 * @return
	 * @throws SignatureException 
	 * @throws InvalidKeyException 
	 * @throws NoSuchAlgorithmException 
	 */
	public boolean verifySign(byte[] data, byte[] signatureData) throws SignatureException, InvalidKeyException, NoSuchAlgorithmException
	{
        Signature signature = Signature.getInstance(this._SigAlgName);
        signature.initVerify(this._PubKey);
        signature.update(data);
        return signature.verify(signatureData);
	}
}
